package com.augurit.common.common.http.kt.interceptor

import com.augurit.common.common.http.kt.model.HttpResultErrorException
import com.example.armmvvm.http.kt.interceptor.ZipHelper
import okhttp3.*
import okio.Buffer
import org.json.JSONObject
import java.io.IOException
import java.nio.charset.Charset
import java.util.*

/**
 *  author : yanghaozhang
 *  date : 2022/5/4 20:46
 *  description :
 */
class DrainageGlobalHttpHandler : GlobalHttpHandler {
    override fun onHttpRequestBefore(chain: Interceptor.Chain, request: Request): Request {
        return request
    }

    override fun onHttpResultResponse(chain: Interceptor.Chain, response: Response): Response {
        val responseBody = response.body()
        responseBody ?: return response

        if (isParseable(responseBody.contentType())) {
            // 如果返回的是xml,接口错误(一般代码错误还是会返回json)或者后台重启
            if (isXml(responseBody.contentType())) {
                throw HttpResultErrorException(false, -1, "接口返回错误,请稍后重试!")
            }

            //获取响应结果
            val bodyString = try {
                getResponseStrBody(response)
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
            bodyString ?: return response

            // 请求成功,但接口报异常,提取接口的提示信息
            val jsonObject = try {
                JSONObject(bodyString)
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
            jsonObject ?: return response

            val isSuccess = jsonObject.optBoolean("success", false)
            val code = jsonObject.optInt("code", -1)
            val message = jsonObject.optString("message", "")
            val msg = jsonObject.optString("msg", "")
            if (!(isSuccess || code == 200)) {
                throw HttpResultErrorException(isSuccess, code, message.ifEmpty { msg }.ifEmpty { "请求接口失败" })
            }
        }
        return response
    }

    fun isParseable(mediaType: MediaType?): Boolean {
        return if (mediaType?.type() == null) {
            false
        } else isJson(mediaType) || isXml(mediaType)
    }

    private fun isJson(mediaType: MediaType?): Boolean {
        return if (mediaType?.subtype() == null) {
            false
        } else mediaType.subtype().toLowerCase(Locale.ROOT).contains("json")
    }

    private fun isXml(mediaType: MediaType?): Boolean {
        return if (mediaType?.subtype() == null) {
            false
        } else mediaType.subtype().toLowerCase(Locale.ROOT).contains("xml")
    }

    @Throws(IOException::class)
    fun getResponseStrBody(response: Response): String? {
        try {
            //读取服务器返回的结果
            val responseBody = response.newBuilder().build().body()
            responseBody ?: return null
            val source = responseBody.source()
            source.request(Long.MAX_VALUE) // Buffer the entire body.
            val buffer = source.buffer()

            //获取content的压缩类型
            val encoding = response.headers()["Content-Encoding"]
            val clone = buffer.clone()

            //解析response content
            return parseContent(responseBody, encoding, clone)
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 解析服务器响应的内容
     *
     */
    private fun parseContent(responseBody: ResponseBody, encoding: String?, clone: Buffer): String {
        var charset = Charset.forName("UTF-8")
        val contentType = responseBody.contentType()
        if (contentType != null) {
            charset = contentType.charset(charset)
        }
        //content 使用 gzip 压缩
        return when {
            "gzip".equals(encoding, ignoreCase = true) -> {
                //解压
                ZipHelper.decompressForGzip(clone.readByteArray(), convertCharset(charset))
            }
            "zlib".equals(encoding, ignoreCase = true) -> {
                //content 使用 zlib 压缩
                ZipHelper.decompressToStringForZlib(clone.readByteArray(), convertCharset(charset))
            }
            else -> {
                //content 没有被压缩, 或者使用其他未知压缩方式
                clone.readString(charset)
            }
        }
    }

    fun convertCharset(charset: Charset?): String {
        val s = charset.toString()
        val i = s.indexOf("[")
        return if (i == -1) {
            s
        } else s.substring(i + 1, s.length - 1)
    }
}